﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using FinPlusCommon;
using log = Logger.Logger;
using u = FinPlusUtility.Utility;


namespace FinPlusComponents
{
    public class QLEngineIndexs : FinPlusComponent
    {
        public override string Id { get; set; }
        public override string[] States { get { return new string[] { }; } }
        public override string[] TestStates { get { return new string[] { "IsValid" }; } }
        public override IFinPlusFunctions Model { get { return null; } }
        public override string ModelTest { get { return null; } }
        public override bool IsValid { get; set; }

        private enum Params { IndexName, Date };
        private enum DockControls { FinPlusDataConn, FinPlusChildService, QLAnalytics, Default }
        private enum Connection { IndexBuilds, IndexHistorys, Exception }
        private enum BuildEvents { Update, Refresh, UpdateAndRefresh }
        
        private IFinPlusComponent _indexBuildConn, _indexHistoryConn;
        private QLAnalytics _analytics;
        private readonly BuildEvents _buildEvents;
        private readonly Indexs _indexs;
        private bool _hasInitialised;

        public QLEngineIndexs(string buildEvents)
        {
            _buildEvents = u.EnumTryParse<BuildEvents>(buildEvents, BuildEvents.UpdateAndRefresh);
            _indexs = new Indexs();
        }

        //common control interface
        public override void Dock(object component, string dock) 
        {
            try
            {
                switch (u.EnumTryParse<DockControls>(component.GetType().Name, DockControls.Default))
                {
                    case DockControls.QLAnalytics: _analytics = (QLAnalytics)component; break;
                    case DockControls.FinPlusChildService:
                    case DockControls.FinPlusDataConn:
                    case DockControls.Default: AddConnection((IFinPlusComponent)component, dock); break;
                }
            }
            catch (Exception e)
            {
                IsValid = log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        public override void Initialise()
        {
            try
            {
                if (_hasInitialised) return;

                foreach (var indexBuild in _indexBuildConn.Model.Values)
                {
                    var indexName = indexBuild[Params.IndexName.ToString()].ToString();
                    var indexHistory = _indexHistoryConn.Model.Where("Name='IndexName' And Value='" + indexName + "'", Params.Date.ToString());
                    _indexs.TryAdd(indexName, new Index(_analytics, indexName, indexBuild, indexHistory, _buildEvents));
                }

                _hasInitialised = IsValid = true;
            }
            catch (Exception e)
            {
                IsValid = log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        public override void Dispose() 
        {
            if (_indexBuildConn == null)
                _indexBuildConn.Dispose();

            if (_indexHistoryConn == null)
                _indexHistoryConn.Dispose();
        }

        public override void CommandRouter(IFinPlusFunction func) { }

        //private
        private void AddConnection(IFinPlusComponent conn, string dock)
        {
            try
            {
                switch (u.EnumTryParse<Connection>(dock, Connection.Exception))
                {
                    case Connection.IndexBuilds: _indexBuildConn = conn; break;
                    case Connection.IndexHistorys: _indexHistoryConn = conn; break;
                    case Connection.Exception: throw new NotImplementedException();
                }
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        private class Indexs : ConcurrentDictionary<string, Index> { }

        private class Index
        {
            private enum Params { IndexName, Instrument, LinkedCurve, CurveName, IndexType, Tenor, Date };
            
            private QLAnalytics _analytics;
            private IFinPlusFunction _indexBuild;
            private string _indexName, _curveName, _indexType, _tenor;
            private IDictionary<string, IFinPlusFunction> _indexHistory;
            private BuildEvents _buildEvents;

            public Index(QLAnalytics analytics, string indexName, IFinPlusFunction indexBuild, IDictionary<string, IFinPlusFunction> indexHistory, BuildEvents buildEvents)
            {
                _analytics = analytics;
                _indexName = indexName;
                _indexBuild = indexBuild;
                _indexHistory = indexHistory;
                _curveName = indexBuild[Params.CurveName.ToString()].ToString();
                _indexType = indexBuild[Params.IndexType.ToString()].ToString();
                _tenor = indexBuild[Params.Tenor.ToString()].ToString();
                _buildEvents = buildEvents;
                BuildIndex();
            }

            private void BuildIndex()
            {
                try
                {
                    lock (_analytics.QL)
                       _analytics.QL.Index(_analytics.MarketName, _curveName, _indexName, _indexType, _tenor, "");//TODO
                }
                catch (Exception e)
                {
                    log.Log(Logger.Level.Error, e.Message, e);
                }
            }
        }
    }
}
